Skip to content
This repository was archived by the owner on Sep 14, 2026. It is now read-only.

fix(mcp): scope HF bearer token to HuggingFace endpoints only - #323

Closed
lockezhou18 wants to merge 1 commit into
huggingface:mainfrom
lockezhou18:fix/scope-hf-bearer-to-hf-endpoints
Closed

lockezhou18 wants to merge 1 commit into
huggingface:mainfrom
lockezhou18:fix/scope-hf-bearer-to-hf-endpoints

Conversation

@lockezhou18

Copy link
Copy Markdown

Problem

ToolRouter.__init__ (agent/core/tools.py) injects Authorization: Bearer <hf_token> into the headers of every configured MCP server:

for name, server in mcp_servers.items():
    data = server.model_dump()
    if hf_token:
        data.setdefault("headers", {})["Authorization"] = f"Bearer {hf_token}"
    mcp_servers_payload[name] = data

Two issues:

  1. Credential leak — the user's HF token is sent to every MCP server they configure, including unrelated/third-party servers that have no business seeing it.
  2. Breaks auth-enforcing servers — a server that grants a default identity to unauthenticated localhost callers (e.g. a self-hosted data-gateway) instead receives an unrecognized hf_... bearer and rejects every tool call. In my setup a local gateway returned invalid_token: bearer token not recognized on all calls; removing the stray header let it fall back to its default localhost identity and work.

Fix

Only attach the HF bearer when the server URL is a HuggingFace endpoint, matched on the parsed hostname (huggingface.co or a subdomain such as router.huggingface.co) rather than a substring — so lookalike hosts like huggingface.co.evil.com don't match. Stdio servers (no URL) and all non-HF remotes now receive no Authorization header.

if hf_token and _is_hf_endpoint(data.get("url")):
    data.setdefault("headers", {})["Authorization"] = f"Bearer {hf_token}"

The default hf-mcp-server (https://huggingface.co/mcp?login) still receives the token unchanged.

Verification

_is_hf_endpoint behavior:

URL Header attached
https://huggingface.co/mcp?login yes
https://router.huggingface.co/v1 yes
http://127.0.0.1:8001/mcp no
https://huggingface.co.evil.com/mcp no
stdio server (no url) no

Confirmed end-to-end: with the default hf-mcp-server plus a local data-gateway MCP, tool calls to both succeed after the change (before, the data-gateway rejected every call with invalid_token).

🤖 Generated with Claude Code

ToolRouter injected `Authorization: Bearer <hf_token>` into the headers of
*every* configured MCP server. This leaks the user's HF token to unrelated
third-party MCP servers, and breaks auth-enforcing servers: a local
data-gateway that grants a default identity to unauthenticated localhost
callers instead receives an unrecognized `hf_...` token and rejects every
tool call with `invalid_token: bearer token not recognized`.

Only attach the HF bearer when the server URL is a HuggingFace endpoint,
matched via the parsed hostname (huggingface.co or a subdomain) so lookalike
hosts like `huggingface.co.evil.com` don't match. Stdio servers (no URL) and
all non-HF remotes now receive no Authorization header.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lewtun

lewtun commented Sep 14, 2026

Copy link
Copy Markdown
Member

Thanks for contributing to ML Intern. The project, including its CLI, has been retired and this repository is being archived. We will therefore not be able to review or merge this work. For continued AI assistance, please use HuggingChat.

@lewtun lewtun closed this Sep 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants